package divestoclimb.checklist;

import java.util.LinkedList;

import divestoclimb.checklist.storage.DbAdapter;

import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ListActivity;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.AdapterView.AdapterContextMenuInfo;

public class SelectCategory extends ListActivity {

	public static final int DIALOG_CONFIRM_DELETE=1;
	
	// These are special items in the Category list.
	public static final int ID_ALL=-1;		// All is used to show items in any
											// category. Doing this involves knowing
											// what queries to make to the database
											// adapter so the logic behind this is
											// handled by the Activity.
	public static final int ID_NEW=-2;		// New launches a separate activity
											// to build a new category and select
											// that one.
	public static final String SHOW_ALL = "show_all";
	public static final int CODE_CATEGORY_CHANGE = 95;
	
	// These are our result codes
	public static final int CODE_REFRESH=10;
	public static final int CODE_CHOOSE=11;
	
	private boolean mShowAll;
	private long mSelectedItem;
	
	private DbAdapter mDbHelper;
	private ArrayAdapter<CategorySpinnerItem> mListAdapter;
	
	/**
	 * We can't just build the category list using a Cursor adapter because we need
	 * to show the "All" option to show all categories. This means we have to build
	 * an ArrayAdapter composed of objects to show Spinner items for. This is that
	 * object.
	 * 
	 * @author Ben Roberts (divestoclimb@gmail.com)
	 */
	public static class CategorySpinnerItem {
		
		private long mId;
		private String mName;
		
		public long getID() { return mId; }
		protected void setID(long id) { mId = id; }
		public String getName() { return mName; }
		public void setName(String name) { mName = name; }
		
		public CategorySpinnerItem(String text, long id) {
			mId=id;
			mName=text;
		}
		
		public String toString() {
			return mName;
		}
	}
	
	@Override
	protected void onCreate(Bundle icicle) {
		super.onCreate(icicle);
		
		Bundle params = icicle != null? icicle: getIntent().getExtras();
		
		mDbHelper = new DbAdapter(this);
		if(params != null) {
			mShowAll = params.getBoolean(SHOW_ALL);
		} else {
			mShowAll = false;
		}
		
		registerForContextMenu(getListView());
	}
	
	@Override
	protected void onPause() {
		super.onPause();
		mDbHelper.close();
	}
	
	@Override
	protected void onResume() {
		super.onResume();
		mDbHelper.open();
		buildList();
	}
	
	private void buildList() {
		Cursor cat_cursor = mDbHelper.fetchAllCategories();
		cat_cursor.moveToFirst();

		// First build the Category list. This begins with the Add option, includes
		// every category returned by all_categories, then ends with the Edit
		// Categories option.
		LinkedList<CategorySpinnerItem> categories = new LinkedList<CategorySpinnerItem>();

		if(mShowAll) {
			categories.add(new CategorySpinnerItem(
					getResources().getString(R.string.all),
					ID_ALL));
		}
		do {
			String name = cat_cursor.getString(cat_cursor.getColumnIndexOrThrow(DbAdapter.KEY_CATEGORY_NAME));
			long id = cat_cursor.getLong(cat_cursor.getColumnIndexOrThrow(DbAdapter.KEY_CATEGORY_ID));
			categories.add(new CategorySpinnerItem(name, id));
		} while(cat_cursor.moveToNext());
		cat_cursor.close();
		categories.add(new CategorySpinnerItem(
				getResources().getString(R.string.new_category),
				ID_NEW));
		
		// Build the spinner adapter and set up the Spinner
		mListAdapter = new ArrayAdapter<CategorySpinnerItem>(this,
				android.R.layout.simple_list_item_1,
				android.R.id.text1,
				categories);
		
		getListView().setAdapter(mListAdapter);
	}
	
	public void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		outState.putBoolean(SHOW_ALL, mShowAll);
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		
		if(requestCode == CODE_CHOOSE && resultCode == RESULT_OK) {
			// Get the new ID from the Intent and return it immediately
			Intent i = new Intent()
				.putExtra(DbAdapter.KEY_CATEGORY_ID, data.getExtras().getLong(DbAdapter.KEY_CATEGORY_ID));
			setResult(RESULT_OK, i);
			finish();
		}
	}
	
	@Override
	protected Dialog onCreateDialog(int id) {
		switch(id) {
		case DIALOG_CONFIRM_DELETE:
			return new AlertDialog.Builder(this)
			.setIcon(android.R.drawable.ic_dialog_alert)
			.setTitle(R.string.confirm_delete)
			.setMessage(R.string.confirm_category_delete)
			.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int whichButton) {
					mDbHelper.deleteCategory(mSelectedItem);
					buildList();
				}
			})
			.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() {
				public void onClick(DialogInterface dialog, int whichButton) {
					// Do nothing
				}
			})
			.create();
		}
		return null;
	}
	
	@Override
	public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
		super.onCreateContextMenu(menu, v, menuInfo);
		if(v instanceof ListView) {
			long id = mListAdapter.getItem(((AdapterView.AdapterContextMenuInfo)menuInfo).position).getID();
			int menuid;
			if(id == ID_ALL || id == ID_NEW || id == DbAdapter.KEY_CATEGORY_ID_UNFILED) {
				// Can't edit or delete the "All", "Unfiled", or "New..." items.
				// If we return now, a click is registered on this item which is
				// probably not intended. We have to display a dummy menu to avoid
				// this.
				menuid=R.menu.cant_edit;
			} else {
				menuid=R.menu.category_list_context;
			}
			MenuInflater inflater = getMenuInflater();
			inflater.inflate(menuid, menu);
		}
	}
	
	@Override
	public boolean onContextItemSelected(MenuItem item) {
		AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
		mSelectedItem = mListAdapter.getItem(info.position).getID();
		switch(item.getItemId()) {
		case R.id.rename:
			Intent i = new Intent(this, CategoryName.class)
				.putExtra(DbAdapter.KEY_CATEGORY_ID, mSelectedItem);
			startActivityForResult(i, CODE_REFRESH);
			break;
		case R.id.delete:
			showDialog(DIALOG_CONFIRM_DELETE);
		}
		return false;
	}

	@Override
	protected void onListItemClick(ListView l, View v, int position, long id) {
		super.onListItemClick(l, v, position, id);
		CategorySpinnerItem item = (CategorySpinnerItem) l.getItemAtPosition(position);
		long my_id=item.getID();
		if(my_id == ID_NEW) {
			startActivityForResult(new Intent(this, CategoryName.class), CODE_CHOOSE);
		} else {
			// Return the selected category back to the Activity that started us
			Intent returnIntent = new Intent()
				.putExtra(DbAdapter.KEY_CATEGORY_ID, my_id);
			setResult(RESULT_OK, returnIntent);
			finish();
		}
	}
}